package admin

import (
	"fmt"
	"geekai/api/dto/common"
	"geekai/api/dto/request"
	"geekai/api/dto/response"
	"geekai/api/handler"
	"geekai/core"
	"geekai/core/types"
	"geekai/model"
	"geekai/utils"
	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
)

type ChatHandler struct {
	handler.BaseHandler
}

func NewChatHandler(app *core.AppServer, db *gorm.DB) *ChatHandler {
	return &ChatHandler{BaseHandler: handler.BaseHandler{App: app, DB: db}}
}

// ChatList godoc
// @Summary      获取会话列表
// @Description  获取会话列表
// @Tags         后台管理-对话管理
// @Accept       json
// @Produce      json
// @Param        req   body     request.ChatListReq  true  "会话查询条件"
// @Success      200  {object}  types.BizVo{data=response.Page}
// @Router       /api/admin/chat/chatList [post]
// @Security AdminApiKeyAuth
func (h *ChatHandler) ChatList(c *gin.Context) {
	var data request.ChatListReq
	if err := c.ShouldBindJSON(&data); err != nil {
		utils.ERROR(c, types.InvalidArgs)
		return
	}

	session := h.DB.Session(&gorm.Session{})
	if data.Title != "" {
		session = session.Where("title like ?", fmt.Sprintf("%s%s%s", "%", data.Title, "%"))
	}
	if data.UserId > 0 {
		session = session.Where("user_id = ?", data.UserId)
	}
	if data.Model != "" {
		session = session.Where("model = ?", data.Model)
	}

	if len(data.CreatedAt) == 2 {
		start := data.CreatedAt[0] + " 00:00:00"
		end := data.CreatedAt[1] + " 23:59:59"
		session = session.Where("created_at >= ? and created_at <= ?", start, end)
	}

	var total int64
	// 查询会话数量
	session.Model(&model.ChatItem{}).Count(&total)
	var items []model.ChatItem
	var list = make([]response.ChatItem, 0)
	offset := (data.Page - 1) * data.PageSize
	res := session.Order("id DESC").Offset(offset).Limit(data.PageSize).Find(&items)
	if res.Error == nil {
		userIds := make([]uint, 0)
		chatIds := make([]string, 0)
		roleIds := make([]uint, 0)

		for _, item := range items {
			userIds = append(userIds, item.UserId)
			chatIds = append(chatIds, item.ChatId)
			roleIds = append(roleIds, item.RoleId)
		}

		var messages []model.ChatMessage
		var users []model.User
		var roles []model.ChatRole
		// 查询会话消息
		h.DB.Where("chat_id IN ?", chatIds).Find(&messages)
		// 查询用户
		h.DB.Where("id IN ?", userIds).Find(&users)
		// 查询应用角色
		h.DB.Where("id IN ?", roleIds).Find(&roles)

		// 存储会话token消耗数量
		tokenMap := make(map[string]int)
		// 用户map，key:用户Id val:用户名
		userMap := make(map[uint]string)
		// 会话对应的消息总数
		msgMap := make(map[string]int)
		// 应用角色map，key:应用角色Id
		roleMap := make(map[uint]response.ChatRole)
		for _, msg := range messages {
			// 累加会话消耗的token总数
			tokenMap[msg.ChatId] += msg.Tokens
			// 累加会话的消息数量
			msgMap[msg.ChatId] += 1
		}
		for _, user := range users {
			userMap[user.Id] = user.Username
		}
		for _, r := range roles {
			var roleResp response.ChatRole
			err := utils.CopyObject(r, &roleResp)
			if err != nil {
				continue
			}
			roleMap[r.Id] = roleResp
		}
		for _, item := range items {
			list = append(list, response.ChatItem{
				Username:  userMap[item.UserId],
				UserId:    item.UserId,
				ChatId:    item.ChatId,
				Title:     item.Title,
				Role:      roleMap[item.RoleId],
				Model:     item.Model,
				Token:     tokenMap[item.ChatId],
				CreatedAt: item.CreatedAt.Unix(),
				MsgNum:    msgMap[item.ChatId],
			})
		}
	}
	utils.SUCCESS(c, response.NewPage(total, data.Page, data.PageSize, list))
}

// MessagesList godoc
// @Summary      读取聊天记录列表
// @Description  读取聊天记录列表
// @Tags         后台管理-对话管理
// @Accept       json
// @Produce      json
// @Param        req   body     request.ChatMessageListReq  true  "聊天消息查询条件"
// @Success      200  {object}  types.BizVo{data=response.Page}
// @Router       /api/admin/chat/messagesList [post]
// @Security AdminApiKeyAuth
func (h *ChatHandler) MessagesList(c *gin.Context) {
	var data request.ChatMessageListReq
	if err := c.ShouldBindJSON(&data); err != nil {
		utils.ERROR(c, types.InvalidArgs)
		return
	}

	session := h.DB.Session(&gorm.Session{})
	if data.Content != "" {
		session = session.Where("content like ?", fmt.Sprintf("%s%s%s", "%", data.Content, "%"))
	}

	if data.UserId > 0 {
		session = session.Where("user_id = ?", data.UserId)
	}

	if data.Model != "" {
		session = session.Where("model = ?", data.Model)
	}
	// 按照时间范围进行查询
	if len(data.CreatedAt) == 2 {
		start := data.CreatedAt[0] + " 00:00:00"
		end := data.CreatedAt[1] + " 23:59:59"
		session = session.Where("created_at >= ? and created_at <= ?", start, end)
	}

	var total int64
	// 查询消息总数
	session.Model(&model.ChatMessage{}).Count(&total)
	var items []model.ChatMessage
	var list = make([]response.ChatMessage, 0)
	// 分页偏移
	offset := (data.Page - 1) * data.PageSize
	// 查询消息列表
	res := session.Order("id DESC").Offset(offset).Limit(data.PageSize).Find(&items)
	if res.Error == nil {
		// 用户Id集合
		userIds := make([]uint, 0)
		for _, item := range items {
			userIds = append(userIds, item.UserId)
		}
		var users []model.User
		// 查询用户信息
		h.DB.Where("id IN ?", userIds).Find(&users)
		// 把用户的 Id 和 用户名 组成 map
		userMap := make(map[uint]string)
		for _, user := range users {
			userMap[user.Id] = user.Username
		}
		for _, item := range items {
			list = append(list, response.ChatMessage{
				Id:        item.Id,
				UserId:    item.UserId,
				Username:  userMap[item.UserId],
				Content:   item.Content,
				Type:      item.Type,
				Model:     item.Model,
				Tokens:    item.Tokens,
				Icon:      item.Icon,
				CreatedAt: item.CreatedAt.Unix(),
			})
		}
	}
	utils.SUCCESS(c, response.NewPage(total, data.Page, data.PageSize, list))
}

// History godoc
// @Summary      获取会话聊天历史记录
// @Description  获取会话聊天历史记录
// @Tags         后台管理-对话管理
// @Accept       json
// @Produce      json
// @Param        chat_id   query     string  true  "会话Id"
// @Success      200  {object}  types.BizVo{data=[]common.HistoryMessage}
// @Router       /api/admin/chat/history [get]
// @Security AdminApiKeyAuth
func (h *ChatHandler) History(c *gin.Context) {
	chatId := h.GetTrim(c, "chat_id")
	var items []model.ChatMessage
	var messages = make([]common.HistoryMessage, 0)
	res := h.DB.Where("chat_id = ?", chatId).Find(&items)
	if res.Error != nil {
		utils.ERROR(c, "操作数据库出错："+res.Error.Error())
		return
	} else {
		for _, item := range items {
			var v common.HistoryMessage
			err := utils.CopyObject(item, &v)
			if err == nil {
				v.CreatedAt = item.CreatedAt.Unix()
				v.UpdatedAt = item.UpdatedAt.Unix()
				messages = append(messages, v)
			}
		}
	}
	utils.SUCCESS(c, messages)
}

// RemoveChat godoc
// @Summary      删除会话
// @Description  删除会话
// @Tags         后台管理-对话管理
// @Accept       json
// @Produce      json
// @Param        chat_id   query     string  true  "会话Id"
// @Success      200  {object}  types.BizVo{}
// @Router       /api/admin/chat/removeChat [get]
// @Security AdminApiKeyAuth
func (h *ChatHandler) RemoveChat(c *gin.Context) {
	chatId := h.GetTrim(c, "chat_id")
	if chatId == "" {
		utils.ERROR(c, "请传入 chat_id 参数")
		return
	}

	// 开启事务
	tx := h.DB.Begin()
	// 删除会话中的聊天记录
	res := tx.Unscoped().Debug().Where("chat_id = ?", chatId).Delete(&model.ChatMessage{})
	if res.Error != nil {
		utils.ERROR(c, "删除会话中的聊天记录失败："+res.Error.Error())
		return
	}
	// 删除会话
	res = h.DB.Unscoped().Where("chat_id = ?", chatId).Delete(&model.ChatItem{})
	if res.Error != nil {
		tx.Rollback() // 回滚
		utils.ERROR(c, "删除会话失败："+res.Error.Error())
		return
	}
	// 提交事务
	tx.Commit()
	utils.SUCCESS(c)
}

// RemoveMessage godoc
// @Summary      删除聊天记录
// @Description  删除聊天记录
// @Tags         后台管理-对话管理
// @Accept       json
// @Produce      json
// @Param        id   query     int  true  "消息Id"
// @Success      200  {object}  types.BizVo{}
// @Router       /api/admin/chat/removeMessage [get]
// @Security AdminApiKeyAuth
func (h *ChatHandler) RemoveMessage(c *gin.Context) {
	id := h.GetInt(c, "id", 0)
	if id <= 0 {
		utils.ERROR(c, types.InvalidArgs)
		return
	}
	// 软删除聊天记录
	err := h.DB.Unscoped().Where("id", id).Delete(&model.ChatMessage{}).Error
	if err != nil {
		utils.ERROR(c, "操作数据库出现错误："+err.Error())
		return
	}
	utils.SUCCESS(c)
}
